package com.yymagicer.core;

import com.yymagicer.util.StringUtil;
import com.yymagicer.util.UnZipUtils;
import net.lingala.zip4j.core.ZipFile;
import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @ClassName ThreadProcessPasswordCrackServiceImpl
 * @Description
 * @Author yangxd
 * @Date 2021/5/7 13:50
 * @Version 1.0
 **/
public class ThreadProcessPasswordCrackServiceImpl implements PasswordCrackService {

    private final ExecutorService executorService;
    private int passwordLength;

    public ThreadProcessPasswordCrackServiceImpl(int passwordLength) {
        this.passwordLength = passwordLength;
        this.executorService = Executors.newFixedThreadPool(THREAD_NUM);
    }

    @Override
    public String run(String source, String dest) {
        long startTime = System.currentTimeMillis();
        Map<String, String> password = new HashMap<>();

        AtomicInteger ai = new AtomicInteger(0);
        List<String> numberStr = new ArrayList<>();
        for (int i = 1; i <= passwordLength; i++) {
            numberStr.addAll(StringUtil.getNumberStr(i));
        }
        long time2 = System.currentTimeMillis();
        System.out.println("生成密码列表耗时：" + (time2 - startTime) + ", 共生成" + numberStr.size() + "个密码");
        List<List<String>> shardingList = getShardingList(numberStr);

        CountDownLatch countDownLatch = new CountDownLatch(shardingList.size());
        shardingList.forEach(list -> {
            executorService.execute(() -> {
                if(password.isEmpty()) {
                    try {
                        String threadName = Thread.currentThread().getName();
                        File zipFile = new File(source);
                        // 首先创建ZipFile指向磁盘上的.zip文件
                        ZipFile zFile = new ZipFile(zipFile);
                        for (int i = 0; i < list.size(); i++) {
                            int times = ai.incrementAndGet();
                            String key = list.get(i);
                            try {
                                zFile.setPassword(key);
                                zFile.setFileNameCharset(StandardCharsets.UTF_8.name());
                                // 将文件抽出到解压目录(解压)
                                zFile.extractAll(dest);
                                password.put(threadName, key);
                                break;
                            } catch (Exception e) {
                                System.out.println(threadName + " \t第" + times + "次密码错误： " + key);
                            }
                            if (!password.isEmpty()) {
                                Map.Entry<String, String> generator = password.entrySet().iterator().next();
                                System.out.println(threadName + " \t密码已找到： " + generator + ", 当前次数：" + times);
                                break;
                            }
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                countDownLatch.countDown();
            });
        });
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        executorService.shutdown();
        final long endTime = System.currentTimeMillis();
        System.out.println("共花费：" + (endTime - startTime) / 1000 + "秒");
        return password.isEmpty() ? null : password.entrySet().iterator().next().getValue();
    }
}
